package com.hyperf.spring.boot.autoconfigure;

import com.hyperf.core.exception.CustomException;
import com.hyperf.event.client.EventFactory;
import com.hyperf.event.client.EventListenerService;
import com.hyperf.event.client.EventMessageListener;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author lizhaoyang
 */
@Slf4j
@Configuration
@EnableConfigurationProperties(EventClientListenerAutoConfiguration.EventClientListenerProperties.class)
@ConditionalOnProperty(prefix = "hyperf.event.listener", name = "enabled", havingValue = "true")
public class EventClientListenerAutoConfiguration implements BeanPostProcessor, BeanFactoryAware {

    private EventListenerService eventListenerService;

    private BeanFactory beanFactory;

    private EventClientListenerProperties properties;

    public EventClientListenerAutoConfiguration(EventClientListenerProperties properties) {
        this.properties = properties;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (eventListenerService == null) {
            eventListenerService = EventFactory.createEventListenerService();
            publishService(properties, eventListenerService);
        }
        if (bean instanceof EventMessageListener) {
            EventMessageListener listener = (EventMessageListener) bean;
            if (listener.isEnabled()) {
                eventListenerService.addListener(listener);
            }
        }
        return bean;
    }

    private void publishService(EventClientListenerProperties properties, EventListenerService eventListenerService) {
        // 当前应用配置
        ApplicationConfig applicationConfig = beanFactory.getBean(ApplicationConfig.class);
        // 连接注册中心配置
        RegistryConfig registry = beanFactory.getBean(RegistryConfig.class);
        // 服务提供者协议配置
        ProtocolConfig protocol = beanFactory.getBean(ProtocolConfig.class);

        // 服务提供者暴露服务配置
        // 此实例很重，封装了与注册中心的连接，请自行缓存，否则可能造成内存和连接泄漏
        ServiceConfig<EventListenerService> service = new ServiceConfig<>();
        service.setInterface(EventListenerService.class);
        service.setRef(eventListenerService);
        service.setVersion(properties.getVersion());
        service.setTimeout(properties.getTimeout());
        service.setApplication(applicationConfig);
        service.setRegistry(registry);
        service.setProtocol(protocol);
        service.export();
    }

    @Data
    @ConfigurationProperties(prefix = "hyperf.event.listener")
    static class EventClientListenerProperties {

        private boolean enabled;

        private String version = "1.0";

        private int timeout;
    }
}
